package com.cheung.shopkeeper.common.utils;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XPathUtil {
	
	static final Log logger = LogFactory.getLog(XPathUtil.class);
	
	private static DocumentBuilderFactory factory;
	
	static {
		factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true); // never forget this!
	}
	
	public static String getStringValue(String targetDoc, String xpathExp, String encoding)
			throws Exception {
		DocumentBuilder builder = factory.newDocumentBuilder();
		
		Document doc = builder.parse(new ByteArrayInputStream(targetDoc.getBytes(encoding)));
		
		XPathFactory pathFactory = XPathFactory.newInstance();
		
		XPath xpath = pathFactory.newXPath();
		
		XPathExpression pathExpression = xpath.compile(xpathExp);
		
		String result = (String) pathExpression.evaluate(doc, XPathConstants.STRING);
		
		return result;
	}
	
	public static HashMap<String, String> getListValue(String targetDoc, List<String> xpathExps,
			String encoding) throws Exception {
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse(new ByteArrayInputStream(targetDoc.getBytes(encoding)));
		
		XPathFactory pathFactory = XPathFactory.newInstance();
		
		XPath xpath = pathFactory.newXPath();
		
		XPathExpression pathExpression;
		String result;
		HashMap<String, String> values = new HashMap<String, String>();
		
		for (String xpathExp : xpathExps) {
			pathExpression = xpath.compile(xpathExp);
			result = (String) pathExpression.evaluate(doc, XPathConstants.STRING);
			values.put(xpathExp, result);
		}
		return values;
	}
	
	/**
	 * @param targetDoc
	 * @param parentNode
	 * @param childNode
	 * @param encoding
	 * @return
	 * @throws Exception
	 */
	public static List<String> getStringValueList(String targetDoc, String parentNode,
			String childNode, String encoding) throws Exception {
		DocumentBuilder builder = factory.newDocumentBuilder();
		//String ss = URLDecoder.decode((String)targetDoc, encoding);
		Document doc = builder.parse(new ByteArrayInputStream(targetDoc.getBytes(encoding)));
		
		NodeList nodeList = doc.getElementsByTagName(parentNode);
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node fatherNode = nodeList.item(i);
			NodeList childNodes = fatherNode.getChildNodes();
			for (int j = 0; j < childNodes.getLength(); j++) {
				Node child = childNodes.item(j);
				if (child instanceof Element) {
					if (child.getNodeName().equals(childNode)) {
						list.add((String) child.getFirstChild().getNodeValue());
					}
				}
			}
		}
		
		return list;
	}
	
	/**
	 * @param targetDoc
	 * @param parentNode
	 * @param childNode
	 * @param encoding
	 * @return
	 * @throws Exception
	 */
	public static List<Object> getNodeValue(String targetDoc, String parentNode, String childNode,
			String encoding) throws Exception {
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse(new ByteArrayInputStream(targetDoc.getBytes(encoding)));
		
		NodeList nodeList = doc.getElementsByTagName(parentNode);
		List<Object> list = new ArrayList<Object>();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node fatherNode = nodeList.item(i);
			NodeList childNodes = fatherNode.getChildNodes();
			for (int j = 0; j < childNodes.getLength(); j++) {
				Node child = childNodes.item(j);
				if (child instanceof Element) {
					if (child.getNodeName().equals(childNode)) {
						list.add((Object) child.getFirstChild().getNodeValue());
					}
				}
			}
		}
		
		return list;
	}
	
	/**
	 * @param targetDoc
	 * @param parentNode
	 * @param childNode
	 * @param encoding
	 * @return child.getFirstChild()==null return ""
	 * @throws Exception
	 */
	public static List<String> getStringValueListDealNull(String targetDoc, String parentNode,
			String childNode, String encoding) throws Exception {
		DocumentBuilder builder = factory.newDocumentBuilder();
		//String ss = URLDecoder.decode((String)targetDoc, encoding);
		Document doc = builder.parse(new ByteArrayInputStream(targetDoc.getBytes(encoding)));
		
		NodeList nodeList = doc.getElementsByTagName(parentNode);
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node fatherNode = nodeList.item(i);
			NodeList childNodes = fatherNode.getChildNodes();
			for (int j = 0; j < childNodes.getLength(); j++) {
				Node child = childNodes.item(j);
				if (child instanceof Element) {
					if (child.getNodeName().equals(childNode)) {
						list.add(child.getFirstChild() == null ? "" : (String) child
								.getFirstChild().getNodeValue());
					}
				}
			}
		}
		
		return list;
	}
	
	public static void main(String[] args) throws Exception {
		String xml = "<rule>  <name>省份</name>  <type>CheckBox</type>  <nodes>	<node>	  <k>ZJ</k>	  <v>浙江</v>	</node>	<node>	  <k>SH</k>	  <v>上海</v>	</node>  </nodes></rule>";
		List<String> ss = getTextContentList(xml, "//nodes/node/v", "UTF-8");
		for (String s : ss) {
			System.out.println(s);
		}
	}
	
	public static List<String> getTextContentList(String xml, String path, String encode)
			throws Exception {
		List<String> result = new ArrayList<String>();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes(encode)));
		XPathFactory pathFactory = XPathFactory.newInstance();
		XPath xpath = pathFactory.newXPath();
		XPathExpression pathExpression = xpath.compile(path);
		NodeList nodeList = (NodeList) pathExpression.evaluate(doc, XPathConstants.NODESET);
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node = nodeList.item(i);
			result.add(node.getTextContent());
		}
		return result;
	}
	
}
